﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using NET.Tools;

namespace Puzzler.Plugin.Interface
{
    public abstract class GridPuzzleRenderer<TModel, TInfo> : PuzzleRenderer<TModel>
        where TModel : GridPuzzleModel<TInfo>
        where TInfo : GridCellInfo
    {
        /// <summary>
        /// Rendering type for...
        /// </summary>
        protected enum GridRendererType
        {
            /// <summary>
            /// Editor render cycle
            /// </summary>
            Editor,
            /// <summary>
            /// Game render cycle
            /// </summary>
            Game,
            /// <summary>
            /// Solution render cycle
            /// </summary>
            Solution
        }

        protected GridPuzzleRenderer(TModel model)
            : base(model)
        {
        }

        protected override sealed void OnDrawEditorView(Canvas canvas)
        {
            OnDraw(canvas, GridRendererType.Editor);
        }

        protected void OnDraw(Canvas canvas, GridRendererType rendererType)
        {
            for (int i = 0; i < Model.GridColumnCount; i++)
            {
                for (int j = 0; j < Model.GridRowCount; j++)
                {
                    TInfo item = Model[i, j];
                    if (item == null)
                    {
                        DrawNullCell(new Rect(i * Model.CellWidth, j * Model.CellHeight, Model.CellWidth, Model.CellHeight), canvas, rendererType);
                    }
                    else
                    {
                        DrawCell(new Rect(i * Model.CellWidth, j * Model.CellHeight, Model.CellWidth, Model.CellHeight), item, canvas, rendererType);
                    }
                }
            }

            //Post Drawing for overdrawing
            for (int i = 0; i < Model.GridColumnCount; i++)
            {
                for (int j = 0; j < Model.GridRowCount; j++)
                {
                    TInfo item = Model[i, j];
                    if (item == null)
                    {
                        PostDrawNullCell(new Rect(i * Model.CellWidth, j * Model.CellHeight, Model.CellWidth, Model.CellHeight), canvas, rendererType);
                    }
                    else
                    {
                        PostDrawCell(new Rect(i * Model.CellWidth, j * Model.CellHeight, Model.CellWidth, Model.CellHeight), item, canvas, rendererType);
                    }
                }
            }

            //Selection (only in editor renderer cycle)
            if (rendererType == GridRendererType.Editor)
            {
                DrawSelection(
                    new Rect(Model.SelectedColumn*Model.CellWidth, Model.SelectedRow*Model.CellHeight, Model.CellWidth,
                             Model.CellHeight), canvas);
            }
        }

        protected virtual void DrawCell(Rect rect, TInfo cellInfo, Canvas canvas, GridRendererType rendererType)
        {
            canvas.AddRectangle(rect, new ShapeStyle(new StrokeStyle(Brushes.Black), new FillStyle(Brushes.White)));
        }

        protected virtual void DrawNullCell(Rect rect, Canvas canvas, GridRendererType rendererType)
        {
            canvas.AddRectangle(rect, new ShapeStyle(new FillStyle(Brushes.White)));
        }

        protected virtual void PostDrawNullCell(Rect rect, Canvas canvas, GridRendererType rendererType)
        {
        }

        protected virtual void PostDrawCell(Rect rect, TInfo cellInfo, Canvas canvas, GridRendererType rendererType)
        {
        }

        protected virtual void DrawSelection(Rect rect, Canvas canvas)
        {
            canvas.AddRectangle(rect, new ShapeStyle(new StrokeStyle(Brushes.Red, 3, DashStyles.Dash)));
        }
    }
}
